Unity 的执行流程
参考资料
Unity 官方文档 Script API
Unity 生命周期
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Unity脚本执行顺序 测试
/// </summary>
public class TestCallSequence : MonoBehaviour
{
void Awake() {
Debug.Log("Awake^^^^^^^^^^^^^");
}
void OnEnable() {
Debug.Log("OnEnable^^^^^^^^^^^^^");
}
// Use this for initialization
void Start() {
Debug.Log("Start^^^^^^^^^^^^^");
}
void FixedUpdate() {
Debug.Log("FixedUpdate^^^^^^^^^^^^^");
}
// Update is called once per frame
void Update() {
Debug.Log("Update^^^^^^^^^^^^^");
}
void LateUpdate() {
Debug.Log("LateUpdate^^^^^^^^^^^^^");
}
void OnGUI() {
Debug.Log("OnGUI^^^^^^^^^^^^^");
}
void Reset() {
Debug.Log("Reset^^^^^^^^^^^^^");
}
void OnDisable() {
Debug.Log("OnDisable^^^^^^^^^^^^^");
}
void OnDestroy() {
Debug.Log("OnDestroy^^^^^^^^^^^^^");
}
}
不同脚本之间的执行顺序
参考资料 浅谈Unity的脚本执行顺序
Unity 中某个脚本的执行顺序是 Awake、Start、Update、LateUpdate 等,但是不同的脚本之间的执行顺序是怎样的呢?
Unity 后台是单线程执行的,所谓的协程都是伪多线程。不同脚本的 Awake 在后台的执行真相是这样的:
后台Awake()
{
脚本0Awake();
脚本1Awake();
........
}
Unity 提供了一个设置不同脚本之间执行顺序的功能,在 Unity 里面可以点击 edit->project settings->Script Execution Order 中自定义脚本执行顺序,order值越小的越先执行,order值越大的越后执行
Update 和 FixedUpdate
void Update()
更新
void FixedUpdate()
固定更新
Update 跟当前平台的帧数有关,而 FixedUpdate 是真实时间,所以处理物理逻辑的时候要把代码放在 FixedUpdate 而不是 Update。
Update 是在每次渲染新的一帧的时候才会调用,也就是说,这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)。在性能好的机器上可能 fps 30,差的可能小些。这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为 Update 的执行间隔不一样了。
而 FixedUpdate,是在固定的时间间隔执行,不受游戏帧率的影响。所以处理 Rigidbody 的时候最好用 FixedUpdate。
LateUpdate
LateUpdate 是在所有 Update 函数调用后被调用。这可用于调整脚本执行顺序。例如:当物体在 Update 里移动时,跟随物体的相机可以在 LateUpdate 里实现。
DontDestroyOnLoad
让该实例切换场景时不被销毁
DontDestroyOnLoad(singleton);
Awake 和 Start 的区别
相同点:
- 两者都是对象初始化时调用的,都在 Update 之前,场景中的对象都生成后才会调用 Awake,Awake 调用完才会调用 Start,所有Start 调用完才会开始 Update。
- 两者在对象生命周期内都只会被调用一次,即初始化时被调用,之后即使是在被重新激活之后也不会再次被调用。
不同点:
- Awake 函数在对象初始化之后立刻就会调用,换句话说,对象初始化之后第一调用的函数就是 Awake;而 Start 是在对象初始化后,第一次 Update 之前调用的,在 Start 中进行初始化不是很安全,因为它可能被其他自定义的函数抢先。
- Awake 不管对象是否是 Active,脚本是否 enabled 都会被调用,可以说是无论如何都会被调用的;而 Start 如果对象被
SetAcive(false)
或者enabled= false
了是不会被调用的。
脚本的一些成员,如果想在创建之后的代码中立即使用,则必须写在 Awake()
里面;(总之和 new
相关的就放在 Awake)
当关卡加载时,脚本的 Awake 的次序是不能控制的;
而开启协程不能在 Awake 中进行,得在 Start 里面开启